package me.flyray.bsin.gateway.portal;

import com.alipay.sofa.rpc.common.json.JSON;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.jwt.JWTPayload;
import cn.hutool.jwt.JWTUtil;
import lombok.extern.slf4j.Slf4j;
import me.flyray.bsin.context.LoginInfoContextHelper;
import me.flyray.bsin.enums.CustomerType;
import me.flyray.bsin.exception.BusinessException;
import me.flyray.bsin.gateway.common.ApiResult;
import me.flyray.bsin.gateway.context.BsinContextBuilder;
import me.flyray.bsin.gateway.service.BsinIpfsRequestHandlerService;
import me.flyray.bsin.utils.BsinServiceInvokeUtil;

/**
 * @author ：bolei
 * @date ：Created in 2022/2/7 17:08
 * @description：开放平台网关入口
 * @modified By：
 */

@Slf4j
@RestController
public class BsinOpenApiPortal {

    @Autowired
    public BsinContextBuilder bsinContextBuilder;
    @Autowired
    public BsinServiceInvokeUtil bsinServiceInvoke;
    @Value("${bsin.s11edao.ipfs.api}")
    private String ipfsApi;
    @Value("${bsin.s11edao.ipfs.gateway}")
    private String ipfsGateway;
    @Autowired
    private BsinIpfsRequestHandlerService bsinIpfsService;

    /**
     * 开放平台接口请求入口
     * 1、通过拦截器验证签名
     * 2、调起服务
     *
     * @param req
     * @return
     */
    @PostMapping("/api-gateway")
    public ApiResult portal(@RequestBody Map<String, Object> req) throws IOException {
        log.info("api-gateway请求参数:{}", JSON.toJSONString(req));
        // 系统参数
        String serviceName = (String) req.get("serviceName");
        String methodName = (String) req.get("methodName");
        String version = (String) req.get("version");
        Map<String, Object> bizParams = (Map<String, Object>) req.get("bizParams");

        ApiResult ipfsResult = bsinIpfsService.ipfsRequestHandler(methodName, bizParams);
        if (ipfsResult != null) {
            return ipfsResult;
        }

        String responseMode = (String) bizParams.get("responseMode");
        //TODO 如果是异步请求方式直接将消息扔到消息队列排队等待
        if ("async".equals(responseMode)) {
            return ApiResult.ok();
        }

        // 签名校验通过后直接生成token
        if ("getAccessToken".equals(methodName)) {
            String token = generateToken(req);
            Map<String, Object> result = new HashMap<>();
            result.put("accessToken", token);
            return ApiResult.ok(result);
        }
        //TODO 判断用户余额是否够，扣费失败无法调用
        // 异步进行计费统计
        String chainEnv = (String) bizParams.get("chainEnv");
        // 测试网和创建钱包地址不需要计费
        if ("BlockChainService".equals(serviceName) && !"createWallet".equals(methodName) && !"test".equals(chainEnv)) {
            Map<String, Object> apiConsumingReq = new HashMap<>();
            apiConsumingReq.put("tenantId", LoginInfoContextHelper.getTenantId());
            apiConsumingReq.put("appId", LoginInfoContextHelper.getAppId());
            apiConsumingReq.put("apiName", methodName);
            try {
                bsinServiceInvoke.billingService(apiConsumingReq);
            } catch (BusinessException e) {
                e.printStackTrace();
                throw e;
            }

        }

        // 1、拼装报文 业务参数
        Map<String, Object> reqParam = bsinContextBuilder.buildReqMessage(req);

        // 3、泛化调用RPC服务
        Map result = new HashMap();
        try {
            result = bsinServiceInvoke.genericInvoke(serviceName, methodName, version, reqParam);
            // TODO 优化项 调用conflux区块链服务返回异常参数
            String detailMessage = (String) result.get("detailMessage");
            if (StringUtils.isNotBlank(detailMessage)) {
                log.info("open api 调用异常 返回参数:{}", detailMessage);
                return ApiResult.fail(detailMessage);
            }
            log.info("open api 调用返回参数:{}", JSON.toJSONString(result));
        } catch (BusinessException e) {
            e.printStackTrace();
            throw e;
        }

        // 4、响应报文处理
        ApiResult apiResult = bsinContextBuilder.buildResMessage(serviceName, methodName, result);
        log.info("api-gateway响应报文返回参数:{}", JSON.toJSONString(apiResult));
        return apiResult;
    }

    /**
     * 根据appId和签名获取token
     * 1、验证签名
     * 2、返回token
     *
     * @param req
     * @return
     */

    private String generateToken(Map<String, Object> req) {
        Map<String, Object> map = new HashMap<String, Object>();
        DateTime now = DateTime.now();
        DateTime newTime = now.offsetNew(DateField.SECOND, 1000);
        //签发时间
        map.put(JWTPayload.ISSUED_AT, now);
        //过期时间
        map.put(JWTPayload.EXPIRES_AT, newTime);
        Map<String, Object> bizParams = (Map<String, Object>) req.get("bizParams");
        //生效时间
        map.put(JWTPayload.NOT_BEFORE, now);
        map.put("tenantId", bizParams.get("tenantId"));
        map.put("customerType", CustomerType.MERCHANT.getCode());
        map.put("appId", bizParams.get("appId"));
        String token = JWTUtil.createToken(map, "1234".getBytes());
        return token;
    }

    /**
     * 开放平台接口请求入口
     *
     * @param req
     * @return
     */
    @PostMapping("/api-gateway/oauth2/token/refreshToken")
    public ApiResult refreshToken(@RequestBody Map<String, String> req) {

        return null;
    }


}
